package com.sinodata.bsm.cicp.util;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;

import org.apache.log4j.Logger;

import com.sinodata.bsm.common.vo.ProtocolParameter;

/**
 * 
 * <p>
 * Description: JMX工具类
 * </p>
 *
 * @author liulibo
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-5-21 上午10:57:31   liulibo        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class JmxUtil {

    private static final Logger logger = Logger.getLogger(JmxUtil.class.getName());
    public static final String WEBLOGIC = "weblogic";

    public static final String WEBSPHERE = "was";

    public static final String WEBSPHERE7 = "was7";

    public static final String TOMCAT = "tomcat";

    public synchronized static JMXConnector getConnection(String ip, Integer port) throws IOException {
        ProtocolParameter protocolParameter = ProtocolParameterUtil.getJmxValue(ip, port);
        if (protocolParameter == null) {
            return null;
        }
        String instType = protocolParameter.getInstType();
        logger.info(instType + "" + WEBLOGIC);
        String username = protocolParameter.getUserName();
        String password = protocolParameter.getPwd();
        return initConnection(instType, ip, port, username, password);
    }

    public synchronized static JMXConnector initConnection(String instType, String ip, Integer port, String username, String password) throws IOException {
        String protocol = "iiop";
        String jndiPath = "/jndi/";
        Map<String, Object> h = new HashMap<String, Object>();
        if (WEBLOGIC.equals(instType)) {
            protocol = "t3";
            jndiPath = "/jndi/weblogic.management.mbeanservers.domainruntime";
            h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");
        } else if (WEBSPHERE.equals(instType)) {
            protocol = "iiop";
            jndiPath = "/jndi/JMXConnector";
        } else if (TOMCAT.equals(instType)) {
            protocol = "rmi:///jndi/rmi";
            jndiPath = "/jmxrmi";
        }
        String serviceURLString = "service:jmx" + ":" + protocol + "://" + ip + ":" + port + jndiPath;
        JMXServiceURL serviceURL;
        JMXConnector connector = null;
        try {
            serviceURL = new JMXServiceURL(serviceURLString);
            h.put(Context.SECURITY_PRINCIPAL, username);
            h.put(Context.SECURITY_CREDENTIALS, password);
            if (TOMCAT.equals(instType)) {
                String[] credentials = new String[] { username, password };
                h.put("jmx.remote.credentials", credentials);
                connector = JMXConnectorFactory.connect(serviceURL, h);
            } else {
                connector = JMXConnectorFactory.connect(serviceURL, h);
            }
            return connector;
        } catch (Exception e) {
            logger.error(e);
            if (connector != null) {
                connector.close();
            }
            throw new IOException(e.getMessage());
        }

    }

    // when to close JMXConnector?
    public static void closeConnector(JMXConnector connector) {
        if (connector == null) {
            return;
        }
        try {
            connector.close();
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public static ObjectName[] getAttribute(MBeanServerConnection connection, String objectName, String attributeName) throws Exception {
        ObjectName service = new ObjectName(objectName);
        ObjectName[] objectNames = (ObjectName[]) connection.getAttribute(service, attributeName);
        return objectNames;
    }

    public static Object[] getAttribute(MBeanServerConnection connection, ObjectName objectName, String[] attributeNames) throws Exception {
        int length = attributeNames.length;
        Object[] values = new Object[length];
        AttributeList attributeList = connection.getAttributes(objectName, attributeNames);
        for (int i = 0; i < length; i++) {
            values[i] = ((Attribute) attributeList.get(i)).getValue();
        }

        return values;
    }

    public static Object[] getParentAttribute(MBeanServerConnection connection, ObjectName objectName, String[] attributeNames) throws Exception {
        Integer length = attributeNames.length;
        Object[] values = new Object[length];
        ObjectName parentObjectName = (ObjectName) connection.getAttribute(objectName, "Parent");
        AttributeList attributeList = connection.getAttributes(parentObjectName, attributeNames);
        for (int i = 0; i < length; i++) {
            values[i] = ((Attribute) attributeList.get(i)).getValue();
        }
        return values;
    }

    public static Object[] getChildAttribute(MBeanServerConnection connection, ObjectName objectName, String childObjectNameString, String[] attributeNames) throws Exception {
        Integer length = attributeNames.length;
        Object[] values = new Object[length];
        ObjectName[] childObjectName = (ObjectName[]) connection.getAttribute(objectName, childObjectNameString);
        //  System.out.println("child:" + childObjectName[0]);
        AttributeList attributeList = connection.getAttributes(childObjectName[0], attributeNames);
        for (int i = 0; i < length; i++) {
            values[i] = ((Attribute) attributeList.get(i)).getValue();
        }
        return values;
    }

    public static void printAttributes(String[] attrNames, Object[] values, String types[]) {
        Integer length = attrNames.length;
        StringBuffer printBuffer = new StringBuffer();
        for (int i = 0; i < length; i++) {
            String printLine = null;
            if (types[i].equals("String")) {
                printLine = attrNames[i] + " = " + (String) values[i] + "\r";
            } else if (types[i].equals("Integer")) {
                printLine = attrNames[i] + " = " + values[i] + "\r";
            } else if (types[i].equals("Long")) {
                printLine = attrNames[i] + " = " + values[i] + "\r";
            } else if (types[i].equals("LongTime")) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = new Date((Long) values[i]);
                printLine = attrNames[i] + " = " + sdf.format(date) + "\r";
            }
            printBuffer.append(printLine);
        }
        //System.out.println(printBuffer.toString());
    }

    public static ObjectName createObjectName(String objectNameString) throws Exception {
        return new ObjectName(objectNameString);
    }

    public static void main(String[] args) throws Exception {

    }

}
